package cn.ly.gateway.core.socket.agreement;

import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 求解析器，解析HTTP请求，GET/POST form-data\raw-json
 */
public class RequestParser {

    /**
     * Netty解析的HTTP请求
     */
    private final FullHttpRequest request;

    public RequestParser(FullHttpRequest request) {
        this.request = request;
    }

    /**
     * 简单处理请求路径
     */
    public String getUri() {
        String uri = request.uri();
        int idx = uri.indexOf("?");
        uri = idx > 0 ? uri.substring(0, idx) : uri;
        if (uri.equals("/favicon.ico")) return null;
        return uri;
    }


    /**
     * 解析http请求的参数
     *
     * @return 参数map
     */
    public Map<String, Object> parse() {

        HttpMethod method = request.getMethod();
        if (HttpMethod.GET.equals(method)) {
            Map<String, Object> parameterMap = new HashMap<>(16);
            // 从请求uri中获取参数键值对
            QueryStringDecoder decoder = new QueryStringDecoder(request.getUri());
            decoder.parameters().forEach((key, value) -> {
                parameterMap.put(key, value.get(0));
            });

            return parameterMap;
        } else if (HttpMethod.POST.equals(method)) {
            String contentType = getContentType();
            // 表单
            if ("multipart/form-data".equals(contentType)){
                Map<String, Object> parameterMap = new HashMap<>(16);
                HttpPostRequestDecoder httpPostRequestDecoder = new HttpPostRequestDecoder(request);
                httpPostRequestDecoder.getBodyHttpDatas().forEach(data -> {
                    Attribute attr = (Attribute) data;
                    try {
                        parameterMap.put(attr.getName(),attr.getValue());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                return parameterMap;
            }else if ("application/json".equals(contentType)){
                ByteBuf byteBuf = request.content().copy();
                if (byteBuf.isReadable()){
                    String body = byteBuf.toString(StandardCharsets.UTF_8);
                    // 转换成JSONObject 一个特殊的Map
                    return JSON.parseObject(body);
                }
            }


        }
        // 其余情况暂不支持
        throw new RuntimeException("未实现的请求类型 HttpMethod：" + method);
    }

    /**
     * 获取请求的content type
     *
     * @return content type
     */
    private String getContentType() {
        Map.Entry<String, String> headerEntry = request
                .headers()
                .entries()
                .stream()
                .filter(val -> val.getKey().equals("Content-Type"))
                .findAny().orElse(null);

        assert headerEntry != null;
        String contentType = headerEntry.getValue();
        int idx = contentType.indexOf(";");
        if (idx > 0) {
            return contentType.substring(0, idx);
        }

        return contentType;

    }
}
